<?php
declare (strict_types=1);

namespace app\admin\controller\admin;

use app\admin\annotation\common\Auth;
use app\admin\controller\Admin;
use app\admin\service\admin\I18nService;
use app\common\Constants;
use app\common\facade\TreeHelper;
use think\App;
use think\facade\Cache;
use think\facade\Lang;
use think\facade\Log;
use think\Request;
use app\admin\model\admin\I18n as I18nModel;
use app\admin\validate\admin\I18n as I18nValidate;

class I18n extends Admin
{
    protected $main_version = '1.0.';

    public function __construct(
        App                 $app,
        protected I18nModel $i18nModel
    )
    {
        parent::__construct($app);
        $this->main_version = '1.0.';
    }


    #[Auth('admin:i18n:index')]
    public function index(): \think\response\Json
    {
        try {
            $params = $this->request->post();
            validate(I18nValidate::class)->scene('index')->check($params);
            $query = I18nModel::withPerms(false);
            // 关键字查询
            $query->when(isset($params['keyword']), function ($query) use ($params) {
                $keyword = str_replace(['%', '_'], ['\%', '\_'], $params['keyword']);
                $query->where('segment|lang_key|value', 'like', "%" . $keyword . "%");
            });
            // 可设默认值的查询
            $query->when(array_key_exists('lang_code', $params), function ($query) use ($params) {
                $query->where('lang_code', '=', $params['lang_code'] ?: 'zh-cn');
            });
            // 如果查询参数里面没有 is_leaf 则默认查询非叶子节点（index 默认行为，为了避免全部数据都加载进来）
            // 如果查询参数里面有 is_leaf 则查询所有节点 （树的懒加载时就关心是不是叶子节点了）
            $query->when(!array_key_exists('is_leaf', $params) && empty($params['keyword']), function ($query) use ($params) {
                $query->where('is_leaf', '=', 0);
            });
            // 空值不查询，只有传递参数来，才查询，不可设置默认值
            $query->when(isset($params['status']), function ($query) use ($params) {
                $query->where('status', '=', $params['status']);
            });
            // 展开时查询
            $query->when(isset($params['pid']), function ($query) use ($params) {
                $query->where('pid', '=', $params['pid']);
            });
            $order_by = sort_rules($params['order_by'] ?? 'sort|asc');
            $query->order($order_by);
            $list['data'] = $query->select()->toArray();
            // 为分页数据添加标记，标明是否存在子节点
            $list['data'] = array_map(function ($node) {
                $node['hasChildren'] = $node['is_leaf'] === 0;
                return $node;
            }, $list['data']);
            $list['sort'] = $order_by;
            return $this->success(['data' => $list]);
        } catch (\Exception $e) {
            throw $e;
        }
    }

    #[Auth('admin:i18n:add')]
    public function add(): \think\response\Json
    {
        $post = $this->request->post();
        I18nService::saveNameSpaceData($post);
        $this->updateVersion();
        return $this->success();
    }

    /**
     * 添加命名空间的时候用于选择父级命名空间
     * @return \think\response\Json
     */
    #[Auth(['admin:i18n:add'])]
    public function getNameSpace(): \think\response\Json
    {
        try {
            $lang = Lang::getLangSet();
            $list = I18nModel::field('id,pid,key')
                ->where('is_leaf', '=', 0)
                ->where('status', '=', 1)
                ->where('lang_code', '=', $lang)
                ->select()->toArray();
            // 添加根节点
            $data[] = [
                'id' => 0,
                'pid' => 0,
                'key' => 'root',
                'title' => 'root',
                'children' => $list,
            ];
            $data = TreeHelper::buildTree($data);
            if (empty($data)) {
                return $this->error(['message' => Constants::E_COMMON_RECORD_NOT_FOUND]);
            }
            return $this->success(['data' => $data]);
        } catch (\Exception $e) {
            throw $e;
        }
    }


    #[Auth('admin:i18n:setting')]
    public function setting(): \think\response\Json
    {
        try {
            $data = $this->request->post();
            I18nService::asyncTranslationData($data['key'], $data['translations']);
            $this->updateVersion();
            return $this->success();
        } catch (\Exception $e) {
            trace([
                'code' => $e->getCode(),
                'file' => $e->getFile(),
                'line' => $e->getLine(),
                'message' => $e->getMessage(),
            ]);
            return $this->error(['message' => $e->getMessage()]);
        }
    }


    /**
     * 删除空的命名空间或者删除翻译条目数据
     *
     * @return \think\response\Json
     */
    #[Auth(['admin:i18n:delete'])]
    public function delete(): \think\response\Json
    {
        $ids = $this->request->post('id/a');
        validate(I18nValidate::class)
            ->scene('delete')
            ->check(['ids' => $ids]);
        $pidCount = I18nModel::whereIn('pid', $ids)->count();
        if ($pidCount > 0) {
            return $this->error(['message' => Constants::E_COMMON_HAS_CHILDREN_DATA]);
        }
        $count = I18nModel::destroy($ids);
        $this->updateVersion();
        return $this->success(['data' => $count]);
    }


    /**
     *  添加翻译数据时，用于载入翻译数据
     * @return \think\response\Json
     */
    public function getTransData(): \think\response\Json
    {
        try {
            $post = $this->request->post();
            $data = I18nModel::where('key', '=', $post['key'])
                ->column('value', 'lang_code');
            if (empty($data)) {
                return $this->error(['message' => Constants::E_COMMON_RECORD_NOT_FOUND]);
            }
            return $this->success(['data' => $data]);
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * 系统支持的语言类型
     *
     * @return \think\response\Json
     */
    public function getLangList(): \think\response\Json
    {
        try {
            $langs = I18nModel::field('lang_code as code')->distinct()->select();
            return $this->success([
                'data' => [
                    'languages' => $langs,
                    'version' => $this->getVersion()
                ]
            ]);
        } catch (\Exception $e) {
            throw $e;
        }
    }


    /**
     * 获取多语言翻译数据
     *
     * @return \think\response\Json
     */
    public function getTranslations(): \think\response\Json
    {
        {
            try {
                $code = $this->request->post('code');
                if ($this->app->isDebug()) {
                    $translations = I18nService::fetchTranslationsFromDb($code);
                } else {
                    // 先从缓存获取
                    $cacheKey = Constants::LANG_TRANSLATION_DATA_KEY . $code;
                    $translations = Cache::get($cacheKey);
                    if (!$translations) {
                        $translations = I18nService::fetchTranslationsFromDb($code);
                        $cacheTime = config('rds.lang_cache_time');
                        Cache::set($cacheKey, $translations, $cacheTime);
                    }
                }
                return $this->success([
                    'data' => [
                        'translations' => $translations,
                        'version' => $this->getVersion()
                    ]
                ]);
            } catch (\Exception $e) {
                return $this->error(['message' => Constants::E_SYS_SERVER_INTERNAL_ERROR]);
            }
        }
    }

    private function getVersion()
    {
        $time = time();
        if (Cache::has(Constants::LANG_VERSION_CACHE_KEY) && Cache::get(Constants::LANG_VERSION_CACHE_KEY)) {
            return Cache::get(Constants::LANG_VERSION_CACHE_KEY);
        } else {
            Cache::set(Constants::LANG_VERSION_CACHE_KEY, $this->main_version . $time, 0);
            return $this->main_version . $time;
        }
    }

    private function updateVersion()
    {
        Cache::set(Constants::LANG_VERSION_CACHE_KEY, $this->main_version . time(), 0);
    }


}
